home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Communications / IBTip / Source / Modem.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  5.8 KB  |  313 lines

  1. #import "Modem.h"
  2. #import <stdio.h>
  3. #import <libc.h>
  4. /* int usleep(unsigned int); */
  5. /* Call 'capture' instead of 'write' to perform filtering.
  6.    For now, we replace cr/lf with lf */
  7.  
  8. void capture(int fd, char *buf, int size)
  9. {
  10.   static int lastchar=0;
  11.  
  12.   while (size>0) {
  13.     if (*buf!='\r')
  14.       write(fd,buf,1);
  15.     if (lastchar=='\r' && *buf!='\n') {
  16.       write(fd,&lastchar,1);
  17.       write(fd,buf,1);
  18.     }
  19.     lastchar = *(buf++);
  20.     size--;
  21.   }
  22. }
  23.  
  24. /* need to catch interrupt if user wished to kill
  25.   child process */
  26. void handler(int sig)
  27. {
  28.   return;
  29. }
  30.  
  31. @implementation Modem
  32.   
  33. + newPort:(char *)dev speed:(int)bps
  34. {
  35.   self = [super newReadWriteDevice:dev];
  36.   if (self==nil)
  37.     return self;
  38.   capturefd = (-1);
  39.   sendProt = xmodem1k;
  40.   receiveProt = zmodem;
  41.   [[[[self setRaw] setParity:NOPARITY] unSetCrmod] unSetEcho];
  42.   [self setSpeed:bps];
  43.   return self;
  44. }
  45.  
  46. + newA
  47. {
  48.   return [self newPort:'a' speed:2400];
  49. }
  50.  
  51. + newB
  52. {
  53.   return [self newPort:'b' speed:2400];
  54. }
  55.  
  56. - hangup  // by clearing Data Terminal Ready signal to modem
  57. {
  58.   char buf[200];
  59.   /* the following apparently doesn't work */
  60.   printf("\nAttempting to hang up phone via DTR\n");
  61.   ioctl(fd,TIOCCDTR,0);
  62.   sleep(1);
  63.   ioctl(fd,TIOCSDTR,0);
  64.   printf("\nAttempting to hang up phone\n");
  65.   [self readInto:buf]; // flush modems buffer
  66.   [self writeOut:"+++"];
  67.   sleep(4);
  68.   if ([self readInto:buf] && strncmp(buf,"OK",2)) {
  69.     [self writeOut:"ATH\r"];
  70.     printf("success\n");
  71.   }
  72.   return self;
  73. }
  74.  
  75. - forkExecArgv:(char **)argv
  76. {
  77.   int pid;
  78.   void (*oldhandler)(int);
  79.  
  80.   pid = fork();
  81.   if (pid!=0) {
  82.     oldhandler = signal(SIGINT, handler);
  83.     wait(0);
  84.     fprintf(stderr,"\r\nFile transfer process ended\r\n");
  85.     signal(SIGINT, oldhandler);
  86.     return self;
  87.   }
  88.   /* the child runs with stdin and stdout redirected to modem */
  89.   dup2(fd,0);
  90.   dup2(fd,1);
  91.   execv(argv[0],argv);
  92.   return self;  // this line is never reached
  93. }
  94.  
  95. - receiveZmodem
  96. {
  97.   char *argv[]={"/usr/local/bin/rz",NULL};
  98.   return [self forkExecArgv:argv];
  99. }
  100.   
  101. - sendZmodemFile:(char *)filename
  102. {
  103.   char *argv[10];
  104.   argv[0]="/usr/local/bin/sz";
  105.   argv[1]=filename;
  106.   argv[2]=NULL;
  107.   return [self forkExecArgv:argv];
  108. }
  109.  
  110. - receiveYmodem
  111. {
  112.   char *argv[]={"/usr/local/bin/rb",NULL};
  113.   return [self forkExecArgv:argv];
  114. }
  115.   
  116. - sendYmodemFile:(char *)filename
  117. {
  118.   char *argv[10];
  119.   argv[0]="/usr/local/bin/sb";
  120.   argv[1]=filename;
  121.   argv[2]=NULL;
  122.   return [self forkExecArgv:argv];
  123. }
  124.  
  125. - receiveXmodemFile:(char *)filename
  126. {
  127.   char *argv[10];
  128.   argv[0]="/usr/local/bin/rx";
  129.   argv[1]=filename;
  130.   argv[2]=NULL;
  131.   return [self forkExecArgv:argv];
  132. }
  133.  
  134. - sendXmodemFile:(char *)filename
  135. {
  136.   char *argv[10];
  137.   argv[0]="/usr/local/bin/sx";
  138.   argv[1]=filename;
  139.   argv[2]=NULL;
  140.   return [self forkExecArgv:argv];
  141. }
  142.  
  143. - receiveXmodem1kFile:(char *)filename
  144. {
  145.   char *argv[10];
  146.   argv[0]="/usr/local/bin/rx";
  147.   argv[1]="-k";
  148.   argv[2]=filename;
  149.   argv[3]=NULL;
  150.   return [self forkExecArgv:argv];
  151. }
  152.  
  153. - sendXmodem1kFile:(char *)filename
  154. {
  155.   char *argv[10];
  156.   argv[0]="/usr/local/bin/sx";
  157.   argv[1]="-k";
  158.   argv[2]=filename;
  159.   argv[3]=NULL;
  160.   return [self forkExecArgv:argv];
  161. }
  162.  
  163. - receive
  164. {
  165.   char file[200];
  166.  
  167.   switch (receiveProt) {
  168.   case xmodem:
  169.     printf("\nEnter file in which to receive:");
  170.     scanf("%s",file);
  171.     [self receiveXmodemFile:file];
  172.     break;
  173.   case xmodem1k:
  174.     printf("\nEnter file in which to receive:");
  175.     scanf("%s",file);
  176.     [self receiveXmodem1kFile:file];
  177.     break;
  178.   case ymodem:
  179.     [self receiveYmodem];
  180.     break;
  181.   case zmodem:
  182.     [self receiveZmodem];
  183.     break;
  184.   default:
  185.     fprintf(stderr,"\nIllegal protocol\n\n");
  186.     break;
  187.   }
  188.   return self;
  189. }
  190.  
  191. - sendFile:(char *)filename
  192. {
  193.   switch (sendProt) {
  194.   case xmodem:
  195.     [self sendXmodemFile:filename];
  196.     break;
  197.   case xmodem1k:
  198.     [self sendXmodem1kFile:filename];
  199.     break;
  200.   case ymodem:
  201.     [self sendYmodemFile:filename];
  202.     break;
  203.   case zmodem:
  204.     [self sendZmodemFile:filename];
  205.     break;
  206.   default:
  207.     fprintf(stderr,"\nIllegal protocol\n\n");
  208.     break;
  209.   }
  210.   return self;
  211. }
  212.  
  213. - setProtocol:(char)p dir:(enum direction)dir
  214. {
  215.   enum protocol *prot;
  216.   prot = (dir==tohost)? &sendProt: &receiveProt;
  217.   switch (p) {
  218.   case 'x':
  219.   case 'X':
  220.     *prot = xmodem;
  221.     break;
  222.   case '1':
  223.     *prot = xmodem1k;
  224.     break;
  225.   case 'y':
  226.   case 'Y':
  227.     *prot = ymodem;
  228.     break;
  229.   case 'z':
  230.   case 'Z':
  231.     *prot = zmodem;
  232.     break;
  233.   default:
  234.     fprintf(stderr,"\nIllegal protocol, specify x,y,or z\n\n");
  235.     break;
  236.   }
  237.   return self;
  238. }    
  239.  
  240. - (int) getProtocolDir:(enum direction)dir
  241. {
  242.   enum protocol prot;
  243.   prot = (dir==tohost)? sendProt: receiveProt;
  244.   switch (prot) {
  245.   case xmodem:
  246.     return 'x';
  247.     break;
  248.   case xmodem1k:
  249.     return '1';
  250.     break;
  251.   case ymodem:
  252.     return 'y';
  253.     break;
  254.   case zmodem:
  255.     return 'z';
  256.     break;
  257.   default:
  258.     fprintf(stderr,"\nProtocol Undefined value = %d\n\n",prot);
  259.     break;
  260.   }
  261.   return 0;
  262. }
  263.  
  264. - captureSessionInFile:(char *)filename
  265. {
  266.   capturefd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0644);
  267.   return self;
  268. }
  269.  
  270. - endCapture
  271. {
  272.   close(capturefd);
  273.   capturefd = (-1);
  274.   return self;
  275. }
  276.  
  277. - (BOOL) isCapturing
  278. {
  279.   return (capturefd >= 0);
  280. }
  281.  
  282. - (int) readInto:(char *)buf  //returns number of characters read into buf
  283. {
  284.   int chars;
  285.   chars = [super readInto:buf];
  286.   if (capturefd >= 0) capture(capturefd, buf, chars);
  287.   return chars;
  288. }
  289.  
  290. /* When sending several character strings to a modem,
  291.  * sometimes need to limit the rate.  This simulates
  292.  * typing by hand.
  293.  * The delay is in microseconds, and is only a lower
  294.  * limit.  Because of the overhead of calling usleep(),
  295.  * the pacing is noticeable even when delay = 1 uSec,
  296.  * so I imagine a value of 1 will usually suffice.
  297.  */
  298. - (int) writeOut:(char *)buf paced:(unsigned long)delay
  299. {
  300.   int len = strlen(buf);
  301.   char onechar[2];
  302.   onechar[1]=0;
  303.   while (len-- > 0) {
  304.     onechar[0]=*buf++;
  305.     if ([self writeOut:onechar] < 0)
  306.       return -1;
  307.     usleep(delay);
  308.   }
  309.   return len;
  310. }
  311.  
  312. @end
  313.